# init repo notebook
!git clone https://github.com/rramosp/ppdl.git > /dev/null 2> /dev/null
!mv -n ppdl/content/init.py ppdl/content/local . 2> /dev/null
!pip install -r ppdl/content/requirements.txt > /dev/null

Bayes theorem continuous#

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
from scipy.integrate import quad
from rlxutils import subplots, copy_func
from progressbar import progressbar as pbar
%matplotlib inline
def get_posterior(likelihood_fn, prior_fn, support, atol=1e-5, integration_intervals=1000):
    assert len(support)==2

    xr = np.linspace(*support, integration_intervals)

    Z = np.sum([likelihood_fn(x)*prior_fn(x) for x in xr]) * (xr[1]-xr[0])
    
    posterior_fn = lambda x: copy_func(likelihood_fn)(x) * copy_func(prior_fn)(x) /  Z
    
    return posterior_fn

the posterior of one measurement#

support = [-20,20]

likelihood = lambda x: stats.norm(loc=2,scale=.5).pdf(x)
prior      = lambda x: stats.norm(loc=4,scale=1).pdf(x)
posterior  = get_posterior(likelihood, prior, support)
xr = np.linspace(*support,1000)
plt.plot(xr, likelihood(xr), label="likelihood")
plt.plot(xr, prior(xr), label="prior", color="black", lw=1)
plt.plot(xr, posterior(xr), label="posterior", color="black", lw=4)
plt.grid();
plt.legend();
plt.xlim(0,5);
../_images/2bd7aa46ecf00fdc2aee487aeb320958aac9acd38b03e947ac932b4d2c44289b.png

several measurements#

we repeat the steps above, using the posterior obtained at each step as the prior for next measurement

def estimate_position(
    z_real = 23,
    prior_mean = 20,
    prior_std = 10,
    sensor_sigma = .7,
    support = [-10, 50]
):
    
    initial_prior      = eval(f"lambda x: stats.norm(loc={prior_mean},scale={prior_std}).pdf(x)")
    measurements = np.random.normal(loc=z_real, scale=sensor_sigma, size=10)
    posteriors = []
    
    prior = initial_prior
    for i in pbar(range(len(measurements))):
        # compute the likelihood
        likelihood = eval(f"lambda x: stats.norm(loc={measurements[i]},scale={sensor_sigma}).pdf(x)")
        
        # compute the posterior, stop if integration errors
        posterior = get_posterior(likelihood, prior, support)
        posteriors.append(posterior)

        # the posterior becomes the next prior 
        prior = posteriors[-1]
        
    # plot stuff
    xr = np.linspace(*support, 10000)
    for ax,i in subplots(len(posteriors)+1, n_cols=6):
        if i==0:
            plt.plot(xr, initial_prior(xr), color="steelblue")
            plt.title("prior")
            plt.ylim(0,0.5)
            plt.xlim(z_real-5, z_real+5)
        else:
            plt.plot(xr, posteriors[i-1](xr), color="steelblue")
            plt.title(f"measurement {i}")
            plt.axvline(measurements[i-1], color="black", ls="--")
            plt.xlim(z_real-2, z_real+2)

        plt.grid();
        plt.axvline(z_real, color="black")
    plt.tight_layout()

a very uninformative prior#

observe how, as measurements are processed, the posterior becomes narrower (less uncertainty) and approaches the real value

estimate_position(
    z_real = 23,
    prior_mean = 5,
    prior_std = 20,
    sensor_sigma = .7
)
100% (10 of 10) |########################| Elapsed Time: 0:00:27 Time:  0:00:27
../_images/91c049818a044237c8b1589e9330fdd1cb32ce0dba7434466724cdb8a0d37663.png

a more accurate sensor converges faster and with less ucertainty#

however observe that numerical integration might stop us from processing further measurements

estimate_position(
    z_real = 23,
    prior_mean = 20,
    prior_std = 10,
    sensor_sigma = .2
)
100% (10 of 10) |########################| Elapsed Time: 0:00:28 Time:  0:00:28
../_images/9dff439b6947aaf94fd8db18a6daa9265e9be450a9d70fe0d279394de933384d.png

but if we are very wrong and very confident on our prior, we pay for it#

Wrong mean with a very narrow stdev. It takes many measurements to converge to the real value.

Recall, narrow stdevs anywhere always represent small uncertainty

estimate_position(
    z_real = 23,
    prior_mean = 20,
    prior_std = .2,
    sensor_sigma = .2
)
100% (10 of 10) |########################| Elapsed Time: 0:00:28 Time:  0:00:28
../_images/dd893711c0ec1d94d4e9056d0e918abf33b01a24b2ab8e180f78f32bea1ae308.png